/*
 * INSANE - Interactive Structural Analysis Environment
 *
 * Copyright (C) 2003-2005
 * Universidade Federal de Minas Gerais
 * Escola de Engenharia
 * Departamento de Engenharia de Estruturas
 * 
 * Author's email :    insane@dees.ufmg.br
 * Author's website :  http://www.dees.ufmg.br/insane
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package br.ufmg.dees.insane.solution;

import java.io.Serializable;
import java.util.Iterator;
import java.util.Observer;

import br.ufmg.dees.insane.assembler.Assembler;
import br.ufmg.dees.insane.util.IMatrix;
import br.ufmg.dees.insane.util.IVector;
import br.ufmg.dees.insane.util.LinearEquationSystems;
import br.ufmg.dees.insane.util.LoadCombination;
import br.ufmg.dees.insane.util.SingularMatrixException;

/** A class representing a Linear Solver.
 *@author jamile
 *@version 1.0
 *@since 27/07/2005
 */
public class SteadyState implements Solution, Serializable{

    private static final long serialVersionUID = 1L;

    LinearEquationSystems sel = new LinearEquationSystems();
    Assembler assembler;
    private String label;

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.solution.Solution#getLabel()
     */
    public String getLabel() {
	return label;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.solution.Solution#setLabel(java.lang.String)
     */
    public void setLabel(String label) {
	this.label = label;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.solution.Solution#getAssembler()
     */
    public Assembler getAssembler() {
	return this.assembler;
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.solution.Solution#setAssembler(br.ufmg.dees.insane.assembler.Assembler)
     */
    public void setAssembler(Assembler assembler) {
	this.assembler = assembler;
    }

    public void execute() throws SingularMatrixException
    {

	try 
	{	
	    assembler.init();

	    if (assembler.getSizeOfXu()!=0) 
	    {
		IMatrix cuu = assembler.getCuu();
		Iterator it = this.assembler.getModel().getLoadCombinationsList().iterator();
		while (it.hasNext()){
		    assembler.initLoading();
		    LoadCombination lcomb = (LoadCombination)it.next();
		    System.out.println("Solving for Load Combination "+lcomb.getLabel());
		    sel.setAMatrix(cuu);
		    sel.setBVector(new IVector(assembler.getSizeOfXu()));
		    assembler.setLoading(lcomb);
		    IVector v = assembler.getNp();
		    sel.addToBVector(v);
		    sel.addToBVector(assembler.getEp());
		    sel.addToBVector(this.getCupXp());                   
		    sel.solverX();
		    assembler.setXu(sel.getXVector());

		    sel.setAMatrix(assembler.getCpu());
		    sel.setXVector(assembler.getXu());
		    sel.solverB();
		    sel.subFromBVector(assembler.getEu());
		    sel.addToBVector(this.getCppXp());
		    // Subtracting possibles dual variables previously set.
		    sel.subFromBVector(assembler.getNu());

		    assembler.setNu(sel.getBVector());
		    assembler.setXp();
		    assembler.update();
//		    assembler.init();
		}
	    }
	    else
	    {
		Iterator it = this.assembler.getModel().getLoadCombinationsList().iterator();
		while (it.hasNext()){
		    assembler.initLoading();
		    LoadCombination lcomb = (LoadCombination)it.next();
		    System.out.println("Solving for Load Combination "+lcomb.getLabel());
		    sel.setBVector(new IVector(assembler.getSizeOfXp()));
		    sel.setAMatrix(assembler.getCpu());
		    sel.setXVector(assembler.getXu());
		    sel.solverB();
		    sel.subFromBVector(assembler.getEu());
		    sel.addToBVector(this.getCppXp());
		    // 	Subtracting possibles dual variables previously set. 
		    sel.subFromBVector(assembler.getNu());
		    assembler.setNu(sel.getBVector());

		    assembler.setXp();
		    assembler.update();
//		    assembler.init();
		}
	    }

	} 
	catch (SingularMatrixException e)
	{
	    throw (e);
	} 
	catch (Exception e1)
	{
	    System.out.println("An exception occured during model analysis.");
	    System.out.println(e1.getClass());
	}
    }

    /** Returns the Cup*Xp of this Assembler FemModel.<p>
     * The data is stored in the same order of equations.<br>
     *Ex.: CupXp[0] is related to equation -1.
     *@return The Cup*Xp of this Assembler FemModel.
     */
    private IVector getCupXp()
    {
	IMatrix cup = assembler.getCup();
	IVector fed = new IVector(cup.getNumRow());
	fed.mul(cup, assembler.getXp());
	fed.negate();
	return (fed);
    };

    /** Returns the Cpp*Xp of this Assembler FemModel.<p>
     * The data is stored in the same order of equations.<br>
     *Ex.: CppXp[0] is related to equation -1.
     *@return The Cpp*Xp of this Assembler FemModel.
     */
    private IVector getCppXp()
    {
	IMatrix cpp = assembler.getCpp();
	IVector fed = new IVector (cpp.getNumRow());
	fed.mul(cpp, assembler.getXp());
	return (fed);
    }

    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.solution.Solution#addObserver(java.util.Observer)
     */
    public void addObserver(Observer arg0) {
    };

}//end of SteadyState
